#include<iostream>
#include<memory>
#include"Log.hpp"
#include"Socket.hpp"

using namespace SocketModule;
using namespace LogModule;

class SelectServe
{
    const static int size=sizeof(fd_set)*8;
    const static int defaultfd=-1;
public:
    SelectServe(int port)
    :_listen_sock(std::make_unique<TcpSocket>())
    ,_isrunning(false)
    {
        _listen_sock->BulidListenSocketMethod(port);
        for(int i=0;i<size;i++)
        {
            _fd_arry[i]=defaultfd;
        }
        _fd_arry[0]=_listen_sock->Fd();
    };
    ~SelectServe(){};

    void Start()
    {
        _isrunning=true;
        while(_isrunning)
        {
            fd_set rfds;
            FD_ZERO(&rfds);
            int maxfd=defaultfd;
            for(int i=0;i<size;i++)
            {
                if(_fd_arry[i]==defaultfd) continue;     
                FD_SET(_fd_arry[i],&rfds);
                if(maxfd<_fd_arry[i]) maxfd=_fd_arry[i];
            }
            
            struct timeval timeout{2,0};
            int n=select(maxfd+1,&rfds,nullptr,nullptr,nullptr);
            switch(n)
            {
                case -1:
                    LOG(LogLevel::ERROR)<<"select error";
                    break;
                case 0:
                    LOG(LogLevel::ERROR)<<"time out.....";
                    break;
                default:
                    LOG(LogLevel::INFO)<<"事件就绪，就绪个数n: "<<n;
                    Dispatcher(rfds);
                    break;
            }
        }
        _isrunning=false;
    }
    
    void Dispatcher(fd_set &rfds)
    {
        for(int i=0;i<size;i++)
        {
            if(_fd_arry[i]==defaultfd) continue;
            if(FD_ISSET(_fd_arry[i],&rfds)) 
            {
                if(_fd_arry[i]==_listen_sock->Fd())
                {
                    Accepter();
                }
                else
                {
                    Recver(_fd_arry[i]);
                }
            }
        }        
    }
private:
    std::unique_ptr<Socket> _listen_sock;
    bool _isrunning;
    int _fd_arry[size];


public:
    void IsStop(){_isrunning=false;}
    void Accepter()
    {
        InetAddr client;
        int fd=_listen_sock->Accept(&client);
        if(fd>=0)
        {
            LOG(LogLevel::INFO)<<"get  new link,sockfd: "<<fd<<"  client is"<<client.StringAddr();
        }
        int pos=0;
        for(;pos<size;pos++)
        {
            if(_fd_arry[pos]== defaultfd)  break;
        }
        if(pos==size) 
        { 
            LOG(LogLevel::WARNING)<<"select serve full";
            close(fd);
        }
        else _fd_arry[pos]=fd;
    }

    void Recver(int fd)
    {
        char buffer[1024];
        ssize_t n=recv(fd,buffer,sizeof(buffer)-1,0);
        if(n>0)
        {
            buffer[n]=0;
            std::cout<<buffer<<std::endl;
        }
        else if(n==0)
        {
            LOG(LogLevel::INFO)<<"client quit....";
            for(int i=0;i<size;i++)
            {
                if(_fd_arry[i]==fd) _fd_arry[i]=defaultfd;
            }
              close(fd);
        }
        else
        {
            LOG(LogLevel::ERROR)<<"recv error....";
        }
    }
};